package com.yunshipei.core.utils;

import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;
import android.webkit.MimeTypeMap;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class FileUtils {

    public static String file2String(File file, String charset) {
        StringBuilder sb = new StringBuilder();
        try {
            LineNumberReader reader = new LineNumberReader(new BufferedReader(new InputStreamReader(new FileInputStream(file), charset)));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append(System.getProperty("line.separator"));
            }
            return sb.toString();
        } catch (IOException ignored) {
        }
        return "";
    }

    public static String readFile(String fileName) {
        if (!new File(fileName).exists()) {
            return "";
        }
        String res = "";
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(fileName);
            int length = fis.available();
            byte[] buffer = new byte[length];
            int len = fis.read(buffer);
            res = new String(buffer, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return res;
    }

    public static boolean writeToFile(String savePath, String fileName, InputStream is) {
        File targetFile = makeFilePath(savePath, fileName);
        OutputStream os = null;
        try {
            os = new FileOutputStream(targetFile);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            return true;
        } catch (Exception e) {
            YspLogUtils.d(e.toString());
            e.printStackTrace();
            return false;
        } finally {
            try {
                assert is != null;
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                assert os != null;
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static File makeFilePath(String filePath, String fileName) {
        makeRootDirectory(filePath);
        File file = new File(filePath, fileName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    public static void makeRootDirectory(String filePath) {
        File file = new File(filePath);
        if (!file.exists() || !file.isDirectory()) {
            file.mkdirs();
        }
    }

    public static boolean unZip(File zipFile, String path) throws Exception {
        File targetDirectory = new File(path);
        if (!targetDirectory.exists()) {
            targetDirectory.mkdirs();
        }
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(zipFile)));
        ZipEntry zipEntry;
        int count;
        byte[] buffer = new byte[8192];
        while ((zipEntry = zis.getNextEntry()) != null) {
            File file = new File(targetDirectory, zipEntry.getName());
            File dir = zipEntry.isDirectory() ? file : file.getParentFile();
            if (!dir.isDirectory() && !dir.mkdirs())
                throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
            if (zipEntry.isDirectory()) continue;
            FileOutputStream fos = new FileOutputStream(file);
            while ((count = zis.read(buffer)) != -1) {
                fos.write(buffer, 0, count);
            }
            fos.close();
        }
        zis.close();
        return true;
    }

    public static boolean unZipStream(InputStream inputStream, String path) throws Exception {
        File targetDirectory = new File(path);
        if (!targetDirectory.exists()) {
            targetDirectory.mkdirs();
        }
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(inputStream));
        ZipEntry zipEntry;
        int count;
        byte[] buffer = new byte[8192];
        while ((zipEntry = zis.getNextEntry()) != null) {
            File file = new File(targetDirectory, zipEntry.getName());
            File dir = zipEntry.isDirectory() ? file : file.getParentFile();
            if (!dir.isDirectory() && !dir.mkdirs())
                throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
            if (zipEntry.isDirectory()) continue;
            FileOutputStream fos = new FileOutputStream(file);
            while ((count = zis.read(buffer)) != -1) {
                fos.write(buffer, 0, count);
            }
            fos.close();
        }
        zis.close();
        return true;
    }

    public static void deleteFile(File file) {
        if (file != null && file.exists()) {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null && files.length > 0) {
                    for (File temp : files) {
                        deleteFile(temp);
                    }
                }
                file.delete();
            } else {
                file.delete();
            }
        }
    }

    public static String readAssertResource(Context context, String strAssertFileName) {
        AssetManager assetManager = context.getAssets();
        String strResponse = "";
        try {
            InputStream ims = assetManager.open(strAssertFileName);
            strResponse = getStringFromInputStream(ims);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return strResponse;
    }

    private static String getStringFromInputStream(InputStream a_is) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        String line;
        try {
            br = new BufferedReader(new InputStreamReader(a_is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                }
            }
        }
        return sb.toString();
    }

    public static byte[] toByteArray(String filePath) throws IOException {
        byte[] buffer = null;
        try {
            File file = new File(filePath);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }

    public static void deletePathReal(String path) {
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null && files.length > 0) {
                    for (File temp : files) {
                        deletePathReal(temp.getPath());
                    }
                }
                file.delete();
            } else {
                file.delete();
            }
        }
    }

    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            if (!file.isDirectory()) {
                file.delete();
            } else {
                deletePathReal(file.getAbsolutePath());
            }
        }
    }

    public static void deleteFileHoldPath(String path) {
        File[] files = new File(path).listFiles();
        if (files != null && files.length > 0) {
            for (File file : files) {
                if (file.exists()) {
                    if (!file.isDirectory()) {
                        file.delete();
                    } else {
                        deletePathReal(file.getAbsolutePath());
                    }
                }
            }
        }
    }

    public static byte[] compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > 100) {    //循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();//重置baos即清空baos
            options -= 10;//每次都减少10
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%，把压缩后的数据存放到baos中
        }
        return baos.toByteArray();
    }

    public static File mKDirs(String dir) {
        boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
        String rootDir;
        if (sdCardExist) {
            rootDir = Environment.getExternalStorageDirectory().getAbsolutePath();
        } else {
            rootDir = Environment.getDataDirectory().getAbsolutePath();
        }
        rootDir = rootDir + dir;
        File dirFile = new File(rootDir);
        if (!dirFile.exists())
            dirFile.mkdirs();
        return dirFile;
    }

    /**
     * delete files
     *
     * @param filePath   要删除的文件目录
     * @param retainPath 要删除文件目录中保留下来的文件 or 目录
     */
    public static void deleteFile(String filePath, String retainPath) {
        File file = new File(filePath);
        if (file.exists()) {
            if (!file.isDirectory()) {
                file.delete();
            } else {
                deletePathReal(file.getAbsolutePath(), retainPath);
            }
        }
    }

    public static void deletePathReal(String path, String retainPath) {
        if (path.equals(retainPath))
            return;
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null && files.length > 0) {
                    for (File temp : files) {
                        if (!TextUtils.isEmpty(temp.getPath()) && !temp.getPath().equals(retainPath))
                            deletePathReal(temp.getPath());
                    }
                }
                file.delete();
            } else {
                file.delete();
            }
        }
    }

    public static void deleteDir(File file) {
        if (file.exists() && file.isFile()) {
            file.delete();
        } else if (file.exists() && file.isDirectory()) {
            for (File subFile : file.listFiles()) {
                if (subFile.exists() && subFile.isDirectory()) {
                    deleteDir(subFile);
                } else {
                    subFile.delete();
                }
            }
            file.delete();
        }
    }

    /**
     * 复制单个文件
     *
     * @param oldPath String 原文件路径 如：c:/fqf.txt
     * @param newPath String 复制后路径 如：f:/fqf.txt
     * @return boolean
     */
    public static boolean copyFile(String oldPath, String newPath) {
        File targetFile = new File(newPath);
        File target = makeFilePath(targetFile.getParent(), targetFile.getName());
        boolean isok = true;
        try {
            int byteread = 0;
            File oldfile = new File(oldPath);
            if (oldfile.exists()) { //文件存在时
                InputStream inStream = new FileInputStream(oldPath); //读入原文件
                FileOutputStream fs = new FileOutputStream(target);
                byte[] buffer = new byte[1024];
                while ((byteread = inStream.read(buffer)) != -1) {
                    fs.write(buffer, 0, byteread);
                }
                fs.flush();
                fs.close();
                inStream.close();
            } else {
                isok = false;
            }
        } catch (Exception e) {
            isok = false;
        }
        return isok;

    }

    /**
     * 复制整个文件夹内容
     *
     * @param oldPath String 原文件路径 如：c:/fqf
     * @param newPath String 复制后路径 如：f:/fqf/ff
     * @return boolean
     */
    public static boolean copyFolder(String oldPath, String newPath) {
        boolean isOK = true;
        try {
            (new File(newPath)).mkdirs(); //如果文件夹不存在 则建立新文件夹
            File a = new File(oldPath);
            String[] file = a.list();
            File temp = null;
            for (int i = 0; i < file.length; i++) {
                if (oldPath.endsWith(File.separator)) {
                    temp = new File(oldPath + file[i]);
                } else {
                    temp = new File(oldPath + File.separator + file[i]);
                }

                if (temp.isFile()) {
                    FileInputStream input = new FileInputStream(temp);
                    FileOutputStream output = new FileOutputStream(newPath + "/" + temp.getName());
                    byte[] b = new byte[1024 * 5];
                    int len;
                    while ((len = input.read(b)) != -1) {
                        output.write(b, 0, len);
                    }
                    output.flush();
                    output.close();
                    input.close();
                }
                if (temp.isDirectory()) {//如果是子文件夹
                    copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]);
                }
            }
        } catch (Exception e) {
            isOK = false;
        }
        return isOK;
    }

    /**
     * 解压文件到当前目录，解压失败会再次尝试
     */
    public static boolean unZipRes(File file) throws Exception {
        if (file.isDirectory() || !file.getName().endsWith(".zip")) return false;
        String targetPath = file.getParent() + File.separator;
        boolean success;
        String fileName = file.getName();
        String path = targetPath + fileName.substring(0, fileName.length() - 4) + File.separator;

        if (FileUtils.unZip(file, path)) {
            success = true;
        } else {
            //重试解压一次
            boolean reUnZip = FileUtils.unZip(file, path);
            if (!reUnZip) {
                file.delete();
                FileUtils.deletePathReal(path);
                success = false;
            } else {
                success = true;
            }
        }
        return success;
    }

    public static void openFile(Context context, String fileName) {
        String suffix = "";
        final int idx = fileName.lastIndexOf(".");
        if (idx > 0) {
            suffix = fileName.substring(idx + 1);
        }
        String type = "*/*";
        if (!TextUtils.isEmpty(suffix)) {
            type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(suffix);
        }
        try {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setAction(android.content.Intent.ACTION_VIEW);
            Uri uri = Uri.fromFile(new File(fileName));
            intent.setDataAndType(uri, type);
            context.startActivity(intent);
        } catch (Exception e) {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setAction(android.content.Intent.ACTION_VIEW);
            Uri uri = Uri.fromFile(new File(fileName));
            intent.setDataAndType(uri, "*/*");
            context.startActivity(intent);
        }
    }
}
